ILIAS  trunk Revision v11.0_alpha-3011-gc6b235a2e85
Brick.php
Go to the documentation of this file.
1<?php
2
19declare(strict_types=1);
20
22
26use Closure;
29
34class Brick
35{
38
39 public function __construct()
40 {
41 $this->transform = new Transform();
42 $this->primitives = new Primitives();
43 }
44
45 public function apply(Closure $parse, string $input): Result
46 {
47 return $this->consume($parse, new Intermediate($input))->then(static fn(Intermediate $x): Result => (
48 $x->transform(static fn($value): Result => (
49 new Ok(is_array($value) && !is_string(key($value)) ? current($value) : $value)
50 ))
51 ));
52 }
53
58 public function toTransformation(Closure $parse): Transformation
59 {
60 return new Custom(fn($input) => $this->apply($parse, $input)->value());
61 }
62
68 public function range(int $start, int $end): Closure
69 {
70 return static fn(Intermediate $x, Closure $cc): Result => $cc(
71 $x->value() >= $start && $x->value() <= $end ? $x->accept() : $x->reject()
72 );
73 }
74
78 public function alpha(): Closure
79 {
80 return $this->primitives->simpleEither([
81 $this->range(0x41, 0x5A),
82 $this->range(0x61, 0x7A),
83 ]);
84 }
85
89 public function digit(): Closure
90 {
91 return $this->range(0x30, 0x39);
92 }
93
94 public function either(array $parsers): Closure
95 {
96 return $this->primitives->simpleEither($this->namesFromKeys($parsers));
97 }
98
103 public function sequence(array $parsers): Closure
104 {
105 return $this->primitives->simpleSequence($this->namesFromKeys($parsers));
106 }
107
114 public function repeat(int $min, ?int $max, $parse): Closure
115 {
116 $min = max(0, $min);
117 $max = null === $max ? null : max($min, $max) - $min;
118
119 return $this->primitives->simpleSequence([
120 ...array_fill(0, $min, $parse),
121 $this->primitives->until($max, $parse)
122 ]);
123 }
124
130 public function transformation(Transformation $transformation, Closure $parse): Closure
131 {
132 return $this->transform->to($transformation, $parse);
133 }
134
139 private function namesFromKeys(array $array): array
140 {
141 return array_map(
142 function ($key) use ($array): Closure {
143 $current = $this->primitives->parserFrom($array[$key]);
144 return is_string($key) ? $this->transform->as($key, $current) : $current;
145 },
146 array_keys($array)
147 );
148 }
149
157 private function consume(Closure $parse, Intermediate $intermediate): Result
158 {
159 return $parse($intermediate, static fn(Result $x): Result => $x->then(
160 static fn(Intermediate $x): Result => $x->done() ? new Ok($x) : new Error('EOF not reached.')
161 ));
162 }
163}
A result encapsulates a value or an error and simplifies the handling of those.
Definition: Ok.php:31
Transform values according to custom configuration.
@phpstan-type Continuation Closure(Result<Intermediate>): Result<Intermediate> @phpstan-type Parser C...
Definition: Brick.php:35
toTransformation(Closure $parse)
Definition: Brick.php:58
sequence(array $parsers)
Definition: Brick.php:103
consume(Closure $parse, Intermediate $intermediate)
It just checks if the given input is fully consumed after parsing and rejects the input otherwise.
Definition: Brick.php:157
repeat(int $min, ?int $max, $parse)
Definition: Brick.php:114
range(int $start, int $end)
Definition: Brick.php:68
transformation(Transformation $transformation, Closure $parse)
Definition: Brick.php:130
apply(Closure $parse, string $input)
Definition: Brick.php:45
either(array $parsers)
Definition: Brick.php:94
transform(Closure $transform)
Calls the given closure with all accepted values.
@phpstan-type Continuation Closure(Result<Intermediate>): Result<Intermediate> @phpstan-type Parser C...
Definition: Primitives.php:33
A result encapsulates a value or an error and simplifies the handling of those.
Definition: Result.php:29
then(callable $f)
Get a new result from the callable or do nothing if this is an error.
A transformation is a function from one datatype to another.