adds tests

This commit is contained in:
JOLIMAITRE Matthieu 2024-05-21 05:51:28 +02:00
parent 23529950e9
commit d93ab67edc
11 changed files with 276 additions and 27 deletions

View file

@ -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)

View file

@ -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"]))

View file

@ -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>"]))

View file

@ -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"]))

View file

@ -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)

View file

@ -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"]))

View file

@ -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)

View file

@ -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"]))

View file

@ -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)

View file

@ -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)

View file

@ -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"]))