ILIAS  trunk Revision v11.0_alpha-3011-gc6b235a2e85
Primitives.php
Go to the documentation of this file.
1<?php
2
19declare(strict_types=1);
20
22
26use Closure;
27
33{
34 public function simpleEither(array $parse): Closure
35 {
36 return $this->variadic([$this, 'or2'], $parse);
37 }
38
39 public function simpleSequence(array $parse): Closure
40 {
41 return $this->variadic([$this, 'seq'], $parse);
42 }
43
49 public function until(?int $max, $parse): Closure
50 {
51 if (0 === $max) {
52 return $this->nop();
53 }
54
55 $max = null === $max ? null : $max - 1;
56
57 return $this->simpleEither([
58 $this->nop(),
59 $this->simpleSequence([
60 $parse,
61 $this->lazy([$this, 'until'], $max, $parse)
62 ])
63 ]);
64 }
65
70 public function parserFrom($x): Closure
71 {
72 return $x instanceof Closure ? $x : $this->mustEqual($x);
73 }
74
75 private function or2(Closure $f, Closure $g): Closure
76 {
77 return static fn(Intermediate $x, Closure $cc): Result => (
78 $f($x, $cc)->except(static fn(): Result => $g($x, $cc))
79 );
80 }
81
87 private function seq(Closure $f, Closure $g): Closure
88 {
89 return static fn(Intermediate $x, Closure $cc): Result => $f(
90 $x,
91 static fn(Result $x): Result => (
92 $x->then(static fn(Intermediate $x): Result => $g($x, $cc))
93 ->except(static fn($error): Result => $cc(new Error($error)))
94 )
95 );
96 }
97
102 private function eq(int $atom): Closure
103 {
104 return static fn(Intermediate $x, Closure $cc): Result => $cc(
105 $atom === $x->value() ? $x->accept() : $x->reject()
106 );
107 }
108
117 private function variadic(callable $call, array $parse): Closure
118 {
119 $parse = array_map([$this, 'parserFrom'], $parse);
120
121 return array_reduce(array_slice($parse, 1), $call, $parse[0]);
122 }
123
128 private function mustEqual(string $expected): Closure
129 {
130 if (strlen($expected) === 1) {
131 return $this->eq(ord($expected));
132 } elseif ('' === $expected) {
133 return $this->nop();
134 }
135
136 return $this->simpleSequence(str_split($expected));
137 }
138
142 private function nop(): Closure
143 {
144 return static fn(Intermediate $x, Closure $cc): Result => (
145 $cc(new Ok($x))
146 );
147 }
148
149 private function lazy(callable $call, ...$arguments): Closure
150 {
151 return static fn(Intermediate $x, Closure $cc): Result => (
152 ($call(...$arguments))($x, $cc)
153 );
154 }
155}
A result encapsulates a value or an error and simplifies the handling of those.
Definition: Ok.php:31
@phpstan-type Continuation Closure(Result<Intermediate>): Result<Intermediate> @phpstan-type Parser C...
Definition: Primitives.php:33
variadic(callable $call, array $parse)
Makes a variadic function from a binary one (left associative and requires at leat 1 argument): f(f(a...
Definition: Primitives.php:117
lazy(callable $call,... $arguments)
Definition: Primitives.php:149
or2(Closure $f, Closure $g)
Definition: Primitives.php:75
seq(Closure $f, Closure $g)
Definition: Primitives.php:87
ilErrorHandling $error
Definition: class.ilias.php:69
A result encapsulates a value or an error and simplifies the handling of those.
Definition: Result.php:29