50 lines
971 B
Python
50 lines
971 B
Python
from abc import ABC, abstractmethod
|
|
from typing import Generic, NamedTuple, Protocol, TypeVar
|
|
|
|
|
|
class ParseError(Exception):
|
|
pass
|
|
|
|
|
|
D = TypeVar("D")
|
|
R = TypeVar("R")
|
|
|
|
|
|
class Parser[D, R](Protocol):
|
|
def parse(self, data: D) -> R: ...
|
|
|
|
|
|
P = TypeVar("P")
|
|
|
|
|
|
class PrepareParser(ABC, Parser[D, R], Generic[D, P, R]):
|
|
|
|
@abstractmethod
|
|
def prepare(self, data: D) -> P: ...
|
|
|
|
@abstractmethod
|
|
def extract(self, data: P) -> R: ...
|
|
|
|
def parse(self, data: D) -> R:
|
|
return self.extract(self.prepare(data))
|
|
|
|
|
|
class Context(Protocol):
|
|
data: str
|
|
|
|
|
|
C = TypeVar("C", bound=Context)
|
|
|
|
|
|
class ParsedContext(NamedTuple, Generic[C, D]):
|
|
context: C
|
|
data: D
|
|
|
|
|
|
class ContextParser(PrepareParser[C, ParsedContext[C, P], R], Generic[C, P, R]):
|
|
@abstractmethod
|
|
def prepare_context(self, data: str) -> P: ...
|
|
|
|
def prepare(self, data: C) -> ParsedContext[C, P]:
|
|
return ParsedContext(context=data, data=self.prepare_context(data.data))
|