Skip to content

Instantly share code, notes, and snippets.

@hchasestevens
Last active March 1, 2018 14:52
Show Gist options
  • Select an option

  • Save hchasestevens/3bb5f86b1f46dad60588d7f349bc0071 to your computer and use it in GitHub Desktop.

Select an option

Save hchasestevens/3bb5f86b1f46dad60588d7f349bc0071 to your computer and use it in GitHub Desktop.
Arbitrary FSMs
class FSM(object):
def __init__(self, pattern, mappings=None):
self.pattern = pattern
if mappings is not None:
print(repr(mappings))
self.mappings = {v: k for k, v in mappings.items() if not callable(v)}
self.adv_mappings = {v: k for k, v in mappings.items() if callable(v)}
else:
self.mappings, self.adv_mappings = {}, {}
def where(self, **mappings):
return FSM(
pattern=self.pattern,
mappings={
v: k
for k, v in itertools.chain(
self.mappings.items(),
self.adv_mappings.items(),
{v: k for k, v in mappings.items()}.items()
)
}
)
def translate(self, seq):
for item in seq:
mapped = self.mappings.get(item)
if mapped is not None:
yield mapped
continue
for cond, mapped in self.adv_mappings.items():
if cond(item):
yield mapped
break
else:
yield '\00'
def search(self, seq):
translated = ''.join(self.translate(seq))
print(repr(translated))
match = re.search(self.pattern, translated)
if match is not None:
sl = slice(*match.span())
return sl, seq[sl]
@hchasestevens
Copy link
Author

Usage:

In [26]: FSM('ab+c').where(a=0, b=1, c=2).search([1,2,3,1,2,2,0,0,1,1,1,2,0])
Out[26]: (slice(7, 12, None), [0, 1, 1, 1, 2])

In [27]: FSM('a.b+c').where(a=0, b=1, c=2).search([1,2,3,1,2,2,0,0,1,1,1,2,0])
Out[27]: (slice(6, 12, None), [0, 0, 1, 1, 1, 2])

In [28]: FSM('a.b+c').where(a=0, b=1, c=2, d=lambda x: x >= 3).search([1,2,5,1,2,2,0,0,1,1,1,2,0])
Out[28]: (slice(6, 12, None), [0, 0, 1, 1, 1, 2])

In [29]: FSM('da.b+c').where(a=0, b=1, c=2, d=lambda x: x >= 3).search([1,2,5,1,2,2,0,0,1,1,1,2,0])

In [30]: FSM('d.+a.b+c').where(a=0, b=1, c=2, d=lambda x: x >= 3).search([1,2,5,1,2,2,0,0,1,1,1,2,0])
Out[30]: (slice(2, 12, None), [5, 1, 2, 2, 0, 0, 1, 1, 1, 2])

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment