"""Regexs for Banana"""
class _Special:
def __init__(self, name):
self.name = name
def __repr__(self):
return self.name
START = _Special('START')
END = _Special('END')
class _Final:
def __init__(self, name, nullable):
self.name = name
self.nullable = lambda: nullable
def __call__(self, token):
return failure
def __repr__(self):
return self.name
failure = _Final("failure", 0)
null = _Final("null", 1)
class Pattern:
def __init__(self, *args):
self.args = args
class _After(Pattern):
def nullable(self):
for i in self.args:
if not callable(i) or not i.nullable():
return 0
return 1
def __repr__(self):
return "After%s" % (self.args,)
def __call__(self, token):
pattern = self.args[0]
if callable(pattern):
result = pattern(token)
if result == null:
return After(*self.args[1:])
elif result == failure:
return failure
elif result.nullable():
return Either(After(result, *self.args[1:]), After(*self.args[1:]))
else:
return After(result, *self.args[1:])
elif pattern == token:
return After(*self.args[1:])
else:
return failure
def After(*args):
if failure in args:
return failure
elif not args:
return null
elif len(args) == 1:
return args[0]
else:
return _After(*args)
class _Either(Pattern):
def __repr__(self):
return "Either%s" % (self.args,)
def nullable(self):
for i in self.args:
if callable(i) and i.nullable():
return 1
return 0
def __call__(self, token):
alternatives = []
for pattern in self.args:
if callable(pattern):
result = pattern(token)
if result != failure:
alternatives.append(result)
elif pattern == token:
alternatives.append(null)
if alternatives:
return Either(*alternatives)
else:
return failure
def Either(*args):
if not args:
return null
elif len(args) == 1:
return args[0]
else:
return _Either(*args)
class AtomType:
def nullable(self):
return 0
def __repr__(self):
return "Atom(%s)" % self.klass.__name__
def __init__(self, klass):
self.klass = klass
def __call__(self, token):
if isinstance(token, self.klass):
return null
else:
return failure
integer = AtomType(int)
string = AtomType(str)
def Sequence(*contents):
return After(START, *contents + (END,))
class OneOrMore:
def __init__(self, pattern):
self.pattern = pattern
def nullable(self):
return self.pattern.nullable()
def __repr__(self):
return "OneOrMore(%s)" % (self.pattern,)
def __call__(self, token):
result = self.pattern(token)
if result == null:
return Either(null, self)
elif result == failure:
return failure
else:
return Either(result, After(result, self))
def match(pattern, iterator):
print pattern
for i in iterator:
pattern = pattern(i)
print repr(i).ljust(7), "-->", pattern
if pattern == failure:
break
print "Matched?", pattern.nullable()
match(Sequence("dict", OneOrMore(After(integer, integer))), [START, "dict", 12, 2, 2, 4, END])
syntax highlighted by Code2HTML, v. 0.9.1