Documentation often primes the mental pump. So it was yesterday. In this
post <https://groups.google.com/d/msg/leo-editor/PsB8dTr2Wac/Yh49dHh6BAAJ>
I said:
QQQ
- The results list exists *only* to hold data to be transferred to the
tokens list.
- Syncing the tokens and results lists is the *only* way make this transfer!
- ...significant (non-optional) tokens appear in exactly the same order in
the two lists.
QQQ
Any time I assert that there is only one way of doing something my
subconscious starts screaming at me ;-) Eventually, I realized that the
notion of significant tokens could collapse the problem. Just synchronize
the two token lists on their significant tokens! Instantly everything
becomes dead easy.
Here are the three main methods of the Linker class, shown in simplified
form for clarity:
def assign_links(self, results, tokens, tree):
# Create the lists of significant tokens and results.
sig_tokens = list(filter(self.is_significant, tokens))
sig_results = list(filter(self.is_significant, results))
# Raise an exception if the two lists are not compatible.
self.check(sig_results, sig_tokens)
# Make two-way links between tokens and results.
for r, t in zip(sig_results, sig_tokens):
self.set_links(r, t, tokens)
tx = 0 # The index of the last patched token.
def set_links(self, r, t, tokens):
# Patch all previous assignable tokens.
while self.tx <= t.index:
token = tokens[self.tx]
if self.should_be_assigned(token, r.node):
# Patch the token.
token.node = r.node
# Add the token to r.node.token_list.
token_list = getattr(r.node, 'token_list', [])
r.node.token_list = token_list + [token]
self.tx += 1
def check(self, results, tokens):
n1, n2 = len(results), len(tokens)
assert n1 == n2, (n1, n2)
for r, t in zip(results, tokens):
assert r.kind == t.kind, (repr(r), repr(t))
assert self.compare_values(r, t), (repr(r), repr(t))
Subclasses may override the remaining three helper methods, shown here w/o
docstrings:
def is_significant(self, token):
return (
token.kind in ('name', 'number') or
token.kind == 'op' and token.value != ';')
def compare_values(self, r, t):
if t.kind == 'string':
val = True # to do. Must be more lenient.
else:
val = t.value == r.value
return val
def should_be_assigned(self, token, node):
return token.kind not in ('encoding', 'endmarker', 'ws')
That's all!
*Summary*
The linker is now the simplest thing that could possibly work.
It's also more flexible. Subclasses can define the three helper methods as
they like.
This is the way it is written in The Book.
Edward
--
You received this message because you are subscribed to the Google Groups
"leo-editor" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to [email protected].
To view this discussion on the web visit
https://groups.google.com/d/msgid/leo-editor/b85e78b9-d8bd-4b05-8c2f-946b46969cd1%40googlegroups.com.