Created
January 19, 2017 11:36
-
-
Save justinfay/e082cdb4f8fc00cd96c63960277df270 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# http://theorangeduck.com/page/you-could-have-invented-parser-combinators | |
stream = list('abcdefghijklmnopqrstuvwxyz') | |
def literal(char): | |
""" | |
Parser which matches a character. | |
""" | |
def parser(stream): | |
if stream[0] == char: | |
return stream.pop(0) | |
raise Exception() | |
return parser | |
def or_(parser1, parser2): | |
""" | |
Boolean or statement. | |
""" | |
def parser(stream): | |
try: | |
return parser1(stream) | |
except: | |
return parser2(stream) | |
return parser | |
def and_(parser1, parser2): | |
""" | |
Boolean and statement. | |
""" | |
def parser(stream): | |
return [parser1(stream), parser2(stream)] | |
return parser | |
def apply_(func, parser): | |
""" | |
Parser which applies a func to the result | |
of another parser. | |
""" | |
def _parser(stream): | |
return func(parser(stream)) | |
return _parser | |
def literal_to_int(char): | |
""" | |
Parser which converts characters to ints. | |
""" | |
return apply_(ord, literal(char)) | |
if __name__ == "__main__": | |
# We want to match tokens that begin with either 'ab' | |
# or 'cd'. | |
parser = or_( | |
and_(literal_to_int('a'), literal_to_int('b')), | |
and_(literal_to_int('c'), literal_to_int('d'))) | |
print parser(stream) | |
print stream | |
print parser(stream) | |
print stream | |
print parser(['c', 'd']) | |
try: | |
parser(stream) | |
except Exception: | |
# All good. | |
pass | |
next_parser = literal_to_int('e') | |
print next_parser(stream) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment