Created
August 16, 2020 22:27
-
-
Save dhilst/858244a7f6b06c6929a0b022c362ff53 to your computer and use it in GitHub Desktop.
parse_combinator in python
This file contains 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
from typing import * | |
import re | |
Result = Tuple[str, Any] | |
Parser = Callable[[str], Result] | |
class ParseError(Exception): | |
pass | |
def id_(i): | |
return i | |
def regex(input: str, p: str, f=id_): | |
m = re.match(f"\s*{p}", input) | |
if m is None: | |
raise ParseError("failed to parse expected {p} found {input}") | |
return input[m.end() :], f(m.group(0).strip()) | |
def regexp(pattern: str, f=id_) -> Parser: | |
def inner(input: str): | |
return regex(input, pattern, f) | |
return inner | |
def or_(*parsers: Parser) -> Parser: | |
def inner(input) -> Result: | |
for p in parsers: | |
try: | |
return p(input) | |
except ParseError: | |
continue | |
raise ParseError(f"None of {parsers} suceeded") | |
return inner | |
def sequence(*parsers: Parser) -> Parser: | |
def inner(input) -> Result: | |
res = [] | |
for p in parsers: | |
input, result = p(input) | |
res.append(result) | |
return input, res | |
return inner | |
def parse(input: str, parser: Parser) -> Result: | |
return parser(input) | |
def int_(input: str) -> Result: | |
return regex(input, r"\d+", int) | |
def plusminus(input: str) -> Result: | |
return regex(input, r"[+-]") | |
def expr(input: str) -> Result: | |
return or_(sequence(int_, plusminus, expr), int_)(input) | |
def test1(): | |
res = parse("1", regexp(r"\d", int)) | |
assert ("", 1) == res | |
def test2() -> None: | |
res = parse("1 + 1", sequence(int_, plusminus, int_)) | |
print(res) | |
assert ("", [1, "+", 1]) == res | |
def test3() -> None: | |
res = parse("1 + 1 + 1", expr) | |
print(res) | |
assert ("", [1, "+", 1, [1, "+", 1]]) == res |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment