def sepBy1(parser, sep, keep=False): '''Parses one or more occurrences of 'parser', separated by 'sep'. If keep is True, returns a list of values returned by BOTH 'parser' and 'sep'; otherwise, a list of values returned by 'parser'. ''' rest = fmap(concat, many(sequence(sep, parser))) if keep else many(sep >> parser) return parser >= (lambda h: fmap(prepend(h), rest))
def sepBy1(parser, sep, keep=False): '''Parses one or more occurrences of 'parser', separated by 'sep'. If keep is True, returns a list of values returned by BOTH 'parser' and 'sep'; otherwise, a list of values returned by 'parser'. ''' rest = fmap(concat, many(sequence( sep, parser))) if keep else many(sep >> parser) return parser >= (lambda h: fmap(prepend(h), rest))
def many1(parser): '''Runs 'parser' one or more times. Returns a list of results returned py 'parser'. ''' return parser >= ( lambda head: fmap(lambda tail: [head] + tail, many(parser)))
def endBy1(parser, sep, keep=False): '''Parses one or more occurrences of 'parser', separated and ended by 'sep'. If keep is True, returns a list of values returned by BOTH 'parser' and 'sep'; otherwise, a list of values returned by 'parser'. ''' if keep: parseOne, transform = sequence(parser, sep), concat else: parseOne, transform = parser >= (lambda p: sep >> lift(p)), lambda x: x return fmap(transform, many1(parseOne))
semi = trailing_space(char(';')) colon = trailing_space(char(':')) dot = trailing_space(char('.')) sepBy_ = lambda sep: lambda parser: sepBy(parser, sep) sepBy1_ = lambda sep: lambda parser: sepBy1(parser, sep) semiSep = sepBy_(semi) semiSep1 = sepBy1_(semi) commaSep = sepBy_(comma) commaSep1 = sepBy1_(comma) def updateSign(sign, num): return num * (-1 if sign == '-' else 1) natural = fmap(int, digits) integer = fmap(lambda x: updateSign(*x), sequence(option('', oneOf('-+')), natural)) doublePos = fmap(lambda x: float(''.join(x)), sequence(digits, char('.'), option('0', digits))) double = fmap(lambda x: updateSign(*x), sequence(option('', oneOf('-+')), doublePos)) integerOrDouble = tryP(double) | integer
def many1(parser): '''Runs 'parser' one or more times. Returns a list of results returned py 'parser'. ''' return parser >= (lambda head: fmap(lambda tail: [head] + tail, many(parser)))
def manyR(parser): '''same as 'many', but quickly overflows stack due to recursion limit''' return (parser >= (lambda head: fmap(lambda tail: [head] + tail, manyR(parser)))) | mzero
def manyR(parser): '''same as 'many', but quickly overflows stack due to recursion limit''' return ( parser >= (lambda head: fmap(lambda tail: [head] + tail, manyR(parser)))) | mzero
sepBy_ = lambda sep: lambda parser: sepBy(parser, sep) sepBy1_ = lambda sep: lambda parser: sepBy1(parser, sep) semiSep = sepBy_(semi) semiSep1 = sepBy1_(semi) commaSep = sepBy_(comma) commaSep1 = sepBy1_(comma) def updateSign(sign, num): return num * (-1 if sign == '-' else 1) natural = fmap(int, digits) integer = fmap(lambda x: updateSign(*x), sequence(option('', oneOf('-+')), natural)) doublePos = fmap(lambda x: float(''.join(x)), sequence(digits, char('.'), option('0', digits))) double = fmap(lambda x: updateSign(*x), sequence(option('', oneOf('-+')), doublePos)) integerOrDouble = tryP(double) | integer