adds tests
This commit is contained in:
parent
23529950e9
commit
d93ab67edc
11 changed files with 276 additions and 27 deletions
|
@ -1,3 +1,4 @@
|
|||
from dataclasses import dataclass
|
||||
from typing import Generic, Optional, TypeVar
|
||||
|
||||
from .transformer import Transformer
|
||||
|
@ -6,6 +7,7 @@ from .parser import Parser
|
|||
|
||||
|
||||
P = TypeVar("P")
|
||||
@dataclass
|
||||
class FutureTransform(Transformer[P]):
|
||||
actual: Optional[Transformer[P]]
|
||||
def __init__(self) -> None:
|
||||
|
@ -24,16 +26,16 @@ class FutureTransform(Transformer[P]):
|
|||
|
||||
P = TypeVar("P")
|
||||
class Declare(Generic[P]):
|
||||
parser: Parser[P]
|
||||
parser_: Parser[P]
|
||||
transform: FutureTransform[P]
|
||||
|
||||
def __init__(self) -> None:
|
||||
transform = FutureTransform[P]()
|
||||
self.parser = Parser(transform)
|
||||
self.parser_ = Parser(transform)
|
||||
self.transform = transform
|
||||
|
||||
def p(self):
|
||||
return self.parser
|
||||
def parser(self):
|
||||
return self.parser_
|
||||
|
||||
def define(self, parser: Parser[P]):
|
||||
self.transform.define(parser.inner)
|
||||
|
|
|
@ -9,9 +9,8 @@ L = TypeVar("L")
|
|||
R = TypeVar("R")
|
||||
@dataclass
|
||||
class AndTransform(Transformer[tuple[L, R]]):
|
||||
def __init__(self, left: Transformer[L], right: Transformer[R]):
|
||||
self.left = left
|
||||
self.right = right
|
||||
left: Transformer[L]
|
||||
right: Transformer[R]
|
||||
|
||||
def parse(self, stream: str, at_index: int) -> Result[tuple[L, R]]:
|
||||
result_left = self.left.parse(stream, at_index)
|
||||
|
@ -21,3 +20,26 @@ class AndTransform(Transformer[tuple[L, R]]):
|
|||
if isinstance(result_right, Failure):
|
||||
return result_right
|
||||
return Success((result_left.value, result_right.value), result_right.next_index)
|
||||
|
||||
|
||||
from okipy.lib import test
|
||||
from .just import JustTransform
|
||||
|
||||
|
||||
@test()
|
||||
def test_and_simple(ctx):
|
||||
parser = AndTransform(JustTransform("ar"), JustTransform("bre"))
|
||||
input = "arbre"
|
||||
assert parser.parse(input, 0) == Success(("ar", "bre"), 5)
|
||||
|
||||
@test()
|
||||
def test_and_shifted(ctx):
|
||||
parser = AndTransform(JustTransform("ar"), JustTransform("bre"))
|
||||
input = "..arbre..."
|
||||
assert parser.parse(input, 2) == Success(("ar", "bre"), 7)
|
||||
|
||||
@test()
|
||||
def test_and_none(ctx):
|
||||
parser = AndTransform(JustTransform("ar"), JustTransform("bre"))
|
||||
input = "......"
|
||||
assert parser.parse(input, 2) == Failure(2, set(["ar"]))
|
||||
|
|
|
@ -12,4 +12,26 @@ class EndTransform(Transformer[None]):
|
|||
def parse(self, stream: str, at_index: int) -> Result[None]:
|
||||
if len(stream) == at_index:
|
||||
return Success(None, at_index)
|
||||
return Failure(at_index, set("<end>"))
|
||||
return Failure(at_index, set(["<end>"]))
|
||||
|
||||
|
||||
from okipy.lib import test
|
||||
|
||||
|
||||
@test()
|
||||
def test_end_simple(ctx):
|
||||
parser = EndTransform()
|
||||
input = ""
|
||||
assert parser.parse(input, 0) == Success(None, 0)
|
||||
|
||||
@test()
|
||||
def test_end_shifted(ctx):
|
||||
parser = EndTransform()
|
||||
input = ".."
|
||||
assert parser.parse(input, 2) == Success(None, 2)
|
||||
|
||||
@test()
|
||||
def test_end_fails(ctx):
|
||||
parser = EndTransform()
|
||||
input = "arbre......"
|
||||
assert parser.parse(input, 2) == Failure(2, set(["<end>"]))
|
||||
|
|
|
@ -6,14 +6,33 @@ from ..transformer import Transformer
|
|||
|
||||
@dataclass
|
||||
class JustTransform(Transformer[str]):
|
||||
def __init__(self, word: str):
|
||||
self.word = word
|
||||
self.word_len = len(self.word)
|
||||
word: str
|
||||
|
||||
def parse(self, stream: str, at_index: int) -> Result[str]:
|
||||
end_index = at_index + self.word_len
|
||||
end_index = at_index + len(self.word)
|
||||
prefix = stream[at_index:end_index]
|
||||
if prefix == self.word:
|
||||
return Success(self.word, end_index)
|
||||
return Failure(at_index, set([self.word]))
|
||||
|
||||
|
||||
from okipy.lib import test
|
||||
|
||||
|
||||
@test()
|
||||
def test_just_simple(ctx):
|
||||
parser = JustTransform("arbre")
|
||||
input = "arbre"
|
||||
assert parser.parse(input, 0) == Success("arbre", 5)
|
||||
|
||||
@test()
|
||||
def test_just_shifted(ctx):
|
||||
parser = JustTransform("arbre")
|
||||
input = "..arbre..."
|
||||
assert parser.parse(input, 2) == Success("arbre", 7)
|
||||
|
||||
@test()
|
||||
def test_just_fails(ctx):
|
||||
parser = JustTransform("arbre")
|
||||
input = "arbre......"
|
||||
assert parser.parse(input, 2) == Failure(2, set(["arbre"]))
|
||||
|
|
|
@ -8,8 +8,7 @@ from ..transformer import Transformer
|
|||
T = TypeVar("T")
|
||||
@dataclass
|
||||
class ListTransform(Transformer[list[T]]):
|
||||
def __init__(self, item: Transformer[T]):
|
||||
self.item = item
|
||||
item: Transformer[T]
|
||||
|
||||
def parse(self, stream: str, at_index: int) -> Result[list[T]]:
|
||||
values = list[T]()
|
||||
|
@ -22,3 +21,26 @@ class ListTransform(Transformer[list[T]]):
|
|||
raise Exception("Parsing empty patterns repeatedly.")
|
||||
at_index = result.next_index
|
||||
return Success(values, at_index)
|
||||
|
||||
|
||||
from okipy.lib import test
|
||||
from .just import JustTransform
|
||||
|
||||
|
||||
@test()
|
||||
def test_list_simple(ctx):
|
||||
parser = ListTransform(JustTransform("arbre"))
|
||||
input = "arbrearbrearbre"
|
||||
assert parser.parse(input, 0) == Success(["arbre", "arbre", "arbre"], 15)
|
||||
|
||||
@test()
|
||||
def test_list_shifted(ctx):
|
||||
parser = ListTransform(JustTransform("arbre"))
|
||||
input = "..arbrearbre"
|
||||
assert parser.parse(input, 2) == Success(["arbre", "arbre"], 12)
|
||||
|
||||
@test()
|
||||
def test_list_none(ctx):
|
||||
parser = ListTransform(JustTransform("arbre"))
|
||||
input = "......"
|
||||
assert parser.parse(input, 2) == Success([], 2)
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
from dataclasses import dataclass
|
||||
from typing import Callable, TypeVar
|
||||
from typing import Callable, Generic, TypeVar
|
||||
|
||||
from ..result import Result, Success, Failure
|
||||
from ..transformer import Transformer
|
||||
|
@ -8,8 +8,10 @@ from ..transformer import Transformer
|
|||
I = TypeVar("I")
|
||||
O = TypeVar("O")
|
||||
@dataclass
|
||||
class MapTransform(Transformer[O]):
|
||||
def __init__(self, value: Transformer[I], transform: Callable[[I], O]):
|
||||
class MapTransform(Generic[I, O], Transformer[O]):
|
||||
value: Transformer[I]
|
||||
|
||||
def __init__(self, value: Transformer[I], transform: Callable[[I], O]) -> None:
|
||||
self.value = value
|
||||
self.transform = transform
|
||||
|
||||
|
@ -19,3 +21,26 @@ class MapTransform(Transformer[O]):
|
|||
return result
|
||||
transformed = self.transform(result.value)
|
||||
return Success(transformed, result.next_index)
|
||||
|
||||
|
||||
from okipy.lib import test
|
||||
from .just import JustTransform
|
||||
|
||||
|
||||
@test()
|
||||
def test_map_simple(ctx):
|
||||
parser = MapTransform(JustTransform("arbre"), lambda a: (9, a))
|
||||
input = "arbre"
|
||||
assert parser.parse(input, 0) == Success((9, "arbre"), 5)
|
||||
|
||||
@test()
|
||||
def test_map_shifted(ctx):
|
||||
parser = MapTransform(JustTransform("arbre"), lambda a: (9, a))
|
||||
input = "..arbre....."
|
||||
assert parser.parse(input, 2) == Success((9, "arbre"), 7)
|
||||
|
||||
@test()
|
||||
def test_map_failure(ctx):
|
||||
parser = MapTransform(JustTransform("arbre"), lambda a: (9, a))
|
||||
input = "......"
|
||||
assert parser.parse(input, 2) == Failure(2, set(["arbre"]))
|
||||
|
|
|
@ -8,11 +8,39 @@ from ..transformer import Transformer
|
|||
T = TypeVar("T")
|
||||
@dataclass
|
||||
class OptionTransform(Transformer[Optional[T]]):
|
||||
def __init__(self, value: Transformer[T]):
|
||||
self.value = value
|
||||
value: Transformer[T]
|
||||
|
||||
def parse(self, stream: str, at_index: int) -> Result[Optional[T]]:
|
||||
result = self.value.parse(stream, at_index)
|
||||
if isinstance(result, Success):
|
||||
return Success(result.value, result.next_index)
|
||||
return Success(None, at_index)
|
||||
|
||||
|
||||
from okipy.lib import test
|
||||
from .just import JustTransform
|
||||
|
||||
|
||||
@test()
|
||||
def test_opt_simple(ctx):
|
||||
parser = OptionTransform(JustTransform("arbre"))
|
||||
input = "arbre"
|
||||
assert parser.parse(input, 0) == Success("arbre", 5)
|
||||
|
||||
@test()
|
||||
def test_opt_none(ctx):
|
||||
parser = OptionTransform(JustTransform("arbre"))
|
||||
input = "brear"
|
||||
assert parser.parse(input, 0) == Success(None, 0)
|
||||
|
||||
@test()
|
||||
def test_opt_shifted(ctx):
|
||||
parser = OptionTransform(JustTransform("arbre"))
|
||||
input = "..arbre..."
|
||||
assert parser.parse(input, 2) == Success("arbre", 7)
|
||||
|
||||
@test()
|
||||
def test_opt_none_shifted(ctx):
|
||||
parser = OptionTransform(JustTransform("arbre"))
|
||||
input = "..rbrea..."
|
||||
assert parser.parse(input, 2) == Success(None, 2)
|
||||
|
|
|
@ -9,9 +9,8 @@ L = TypeVar("L")
|
|||
R = TypeVar("R")
|
||||
@dataclass
|
||||
class OrTransform(Transformer[Union[L, R]]):
|
||||
def __init__(self, left: Transformer[L], right: Transformer[R]):
|
||||
self.left = left
|
||||
self.right = right
|
||||
left: Transformer[L]
|
||||
right: Transformer[R]
|
||||
|
||||
def parse(self, stream: str, at_index: int) -> Result[Union[L, R]]:
|
||||
result_left = self.left.parse(stream, at_index)
|
||||
|
@ -21,3 +20,32 @@ class OrTransform(Transformer[Union[L, R]]):
|
|||
if isinstance(result_right, Success):
|
||||
return Success(result_right.value, result_right.next_index)
|
||||
return Failure(at_index, result_left.expected.union(result_right.expected))
|
||||
|
||||
|
||||
from okipy.lib import test
|
||||
from .just import JustTransform
|
||||
|
||||
|
||||
@test()
|
||||
def test_or_simple(ctx):
|
||||
parser = OrTransform(JustTransform("ar"), JustTransform("bre"))
|
||||
input = "arbre"
|
||||
assert parser.parse(input, 0) == Success("ar", 2)
|
||||
|
||||
@test()
|
||||
def test_or_other(ctx):
|
||||
parser = OrTransform(JustTransform("ar"), JustTransform("bre"))
|
||||
input = "brear"
|
||||
assert parser.parse(input, 0) == Success("bre", 3)
|
||||
|
||||
@test()
|
||||
def test_or_shifted(ctx):
|
||||
parser = OrTransform(JustTransform("ar"), JustTransform("bre"))
|
||||
input = "..arbre..."
|
||||
assert parser.parse(input, 2) == Success("ar", 4)
|
||||
|
||||
@test()
|
||||
def test_or_fail(ctx):
|
||||
parser = OrTransform(JustTransform("ar"), JustTransform("bre"))
|
||||
input = "......"
|
||||
assert parser.parse(input, 2) == Failure(2, set(["ar", "bre"]))
|
||||
|
|
|
@ -7,13 +7,40 @@ from ..transformer import Transformer
|
|||
|
||||
@dataclass
|
||||
class RegexTransform(Transformer[str]):
|
||||
def __init__(self, pattern: str):
|
||||
self.pattern = pattern
|
||||
pattern: str
|
||||
|
||||
def parse(self, stream: str, at_index: int) -> Result[str]:
|
||||
do_match = re.match(self.pattern, stream[at_index:])
|
||||
if do_match is None:
|
||||
return Failure(at_index, set(f"<matching '{self.pattern}'>"))
|
||||
return Failure(at_index, set([f"<matching '{self.pattern}'>"]))
|
||||
else:
|
||||
match = do_match[0]
|
||||
return Success(match, at_index + len(match))
|
||||
|
||||
|
||||
from okipy.lib import test
|
||||
|
||||
|
||||
@test()
|
||||
def test_regex_simple(ctx):
|
||||
parser = RegexTransform("arbre")
|
||||
input = "arbre"
|
||||
assert parser.parse(input, 0) == Success("arbre", 5)
|
||||
|
||||
@test()
|
||||
def test_regex_shifted(ctx):
|
||||
parser = RegexTransform("arbre")
|
||||
input = "..arbre..."
|
||||
assert parser.parse(input, 2) == Success("arbre", 7)
|
||||
|
||||
@test()
|
||||
def test_regex_fails(ctx):
|
||||
parser = RegexTransform("arbre")
|
||||
input = "arbre......"
|
||||
assert parser.parse(input, 2) == Failure(2, set(["<matching 'arbre'>"]))
|
||||
|
||||
@test()
|
||||
def test_regex_some(ctx):
|
||||
parser = RegexTransform("[0-3]+")
|
||||
input = "012345"
|
||||
assert parser.parse(input, 0) == Success("0123", 4)
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
from dataclasses import dataclass
|
||||
from typing import Optional, TypeVar
|
||||
from typing import Generic, Optional, TypeVar
|
||||
|
||||
from ..result import Result
|
||||
from ..transformer import Transformer
|
||||
|
@ -13,7 +13,10 @@ from .list import ListTransform
|
|||
T = TypeVar("T")
|
||||
S = TypeVar("S")
|
||||
@dataclass
|
||||
class SepListTransform(Transformer[list[T]]):
|
||||
class SepListTransform(Generic[T, S], Transformer[list[T]]):
|
||||
items: Transformer[T]
|
||||
sep: Transformer[S]
|
||||
|
||||
def __init__(self, items: Transformer[T], sep: Transformer[S]):
|
||||
self.items = items
|
||||
self.sep = sep
|
||||
|
@ -33,3 +36,33 @@ class SepListTransform(Transformer[list[T]]):
|
|||
for (_sep, item) in value[1]:
|
||||
items.append(item)
|
||||
return items
|
||||
|
||||
|
||||
from okipy.lib import test
|
||||
from .just import JustTransform
|
||||
from ..result import Result, Success, Failure
|
||||
|
||||
|
||||
@test()
|
||||
def test_sep_simple(ctx):
|
||||
parser = SepListTransform(JustTransform("arbre"), JustTransform(","))
|
||||
input = "arbre"
|
||||
assert parser.parse(input, 0) == Success(["arbre"], 5)
|
||||
|
||||
@test()
|
||||
def test_sep_alt(ctx):
|
||||
parser = SepListTransform(JustTransform("arbre"), JustTransform(","))
|
||||
input = "arbre,arbre"
|
||||
assert parser.parse(input, 0) == Success(["arbre", "arbre"], 11)
|
||||
|
||||
@test()
|
||||
def test_sep_none(ctx):
|
||||
parser = SepListTransform(JustTransform("arbre"), JustTransform(","))
|
||||
input = ""
|
||||
assert parser.parse(input, 2) == Success([], 2)
|
||||
|
||||
@test()
|
||||
def test_sep_missing_not_failure(ctx):
|
||||
parser = SepListTransform(JustTransform("arbre"), JustTransform(","))
|
||||
input = "arbre,"
|
||||
assert parser.parse(input, 0) == Success(['arbre'], 5)
|
||||
|
|
|
@ -11,8 +11,29 @@ I = TypeVar("I")
|
|||
T = TypeVar("T")
|
||||
@dataclass
|
||||
class ValueTransform(Transformer[T]):
|
||||
value: T
|
||||
|
||||
def __init__(self, ignored: Transformer[I], value: T):
|
||||
self.value = value
|
||||
self.actual = MapTransform(ignored, lambda _: value)
|
||||
|
||||
def parse(self, stream: str, at_index: int) -> Result[T]:
|
||||
return self.actual.parse(stream, at_index)
|
||||
|
||||
|
||||
from okipy.lib import test
|
||||
from .just import JustTransform
|
||||
from ..result import Result, Success, Failure
|
||||
|
||||
|
||||
@test()
|
||||
def test_value_simple(ctx):
|
||||
parser = ValueTransform(JustTransform("arbre"), "Feur")
|
||||
input = "arbre"
|
||||
assert parser.parse(input, 0) == Success("Feur", 5)
|
||||
|
||||
@test()
|
||||
def test_value_failure(ctx):
|
||||
parser = ValueTransform(JustTransform("arbre"), lambda a: (9, a))
|
||||
input = "......"
|
||||
assert parser.parse(input, 2) == Failure(2, set(["arbre"]))
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue