4 ms·
Yes the regex-parsing FSM class in the article looks cleaner with a single coroutine: class FSM: def __init__(self): self.match = False
by glxxyz 7y ago
Yes the regex-parsing FSM class in the article looks cleaner with a single coroutine:
class FSM:
def __init__(self):
self.match = False
self.current_state = self.create_state_machine()
next(self.current_state)
def does_match(self):
return self.match
def send(self, char):
try:
self.current_state.send(char)
except StopIteration:
self.match = False
pass
def create_state_machine(self):
char = yield
if char == 'a':
while True:
char = yield
if char == 'b':
pass
elif char == 'c':
self.match = True
yield
break
else:
break
- OJFord 7y agoThat makes more sense. And we could still break out states into functions without being quite so explicit as in the article (and without the __init__ problem I described): def create_state_machine(self): if yield == 'a': yield from self.q2() def q2(self): while (char := yield) == 'b': pass if char == 'c': self.match = True Or something like that anyway, untested of course. (NB that actually fixes a bug in yours in that it would continue processing 'b's after the 'c' - of course that's still a match for the regex, but the FSM should have stopped.)
- glxxyz 7y agoThanks for pointing that out, I think I fixed it. Not well tested ;) I'm not sure if the way that you're using yield within the if and while statements works correctly. I like the idea of replacing state transitions with method calls but you'll run into recursion depth problems with a state machine that alternates between two states.
- OJFord 7y ago> I'm not sure if the way that you're using yield within the if and while statements works correctly. You're right... Perhaps I'm not so surprised that `if yield == val:` is a SyntaxError, but that `yield` can't be used as an rvalue to a walrus operator (that the `while` example essentially boils down to) surprises me: >>> char = yield File "<stdin>", line 1 SyntaxError: 'yield' outside function >>> >>> # i.e. OK, that's the error we want if it works >>> >>> got_b = (char := yield) == 'b' File "<stdin>", line 1 got_b = (char := yield) == 'b' ^ SyntaxError: invalid syntax