-
-
Notifications
You must be signed in to change notification settings - Fork 72
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[Regex] add first_match() and every_match() functions (#151)
- Loading branch information
Showing
11 changed files
with
481 additions
and
16 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
<?php | ||
|
||
declare(strict_types=1); | ||
|
||
namespace Psl\Regex; | ||
|
||
use Psl\Dict; | ||
use Psl\Type; | ||
|
||
/** | ||
* @param list<array-key> $groups | ||
* | ||
* @return Type\TypeInterface<array<array-key, string>> | ||
* | ||
* @psalm-suppress MixedReturnTypeCoercion - Psalm loses track of the keys. No worries, another psalm plugin fixes this! | ||
*/ | ||
function capture_groups(array $groups): Type\TypeInterface | ||
{ | ||
return Type\shape( | ||
Dict\from_keys( | ||
Dict\unique([0, ...$groups]), | ||
/** | ||
* @return Type\TypeInterface<string> | ||
*/ | ||
static fn(): Type\TypeInterface => Type\string() | ||
) | ||
); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,52 @@ | ||
<?php | ||
|
||
declare(strict_types=1); | ||
|
||
namespace Psl\Regex; | ||
|
||
use Psl\Exception\InvariantViolationException; | ||
use Psl\Type; | ||
|
||
use function preg_match_all; | ||
|
||
/** | ||
* Determine if $subject matches the given $pattern and return every matches. | ||
* | ||
* @template T of array|null | ||
* | ||
* @param non-empty-string $pattern The pattern to match against. | ||
* @param ?Type\TypeInterface<T> $capture_groups What shape does a single set of matching items have? | ||
* | ||
* @throws Exception\RuntimeException If an internal error accord. | ||
* @throws Exception\InvalidPatternException If $pattern is invalid. | ||
* | ||
* @return (T is null ? list<array<array-key, string>> : list<T>)|null | ||
*/ | ||
function every_match( | ||
string $subject, | ||
string $pattern, | ||
?Type\TypeInterface $capture_groups = null, | ||
int $offset = 0 | ||
): ?array { | ||
$matching = Internal\call_preg( | ||
'preg_match_all', | ||
static function () use ($subject, $pattern, $offset): ?array { | ||
$matching = []; | ||
$matches = preg_match_all($pattern, $subject, $matching, PREG_SET_ORDER, $offset); | ||
|
||
return $matches === 0 ? null : $matching; | ||
} | ||
); | ||
|
||
if ($matching === null) { | ||
return null; | ||
} | ||
|
||
$capture_groups ??= Type\dict(Type\array_key(), Type\string()); | ||
|
||
try { | ||
return Type\vec($capture_groups)->coerce($matching); | ||
} catch (InvariantViolationException | Type\Exception\CoercionException $e) { | ||
throw new Exception\RuntimeException('Invalid capture groups', 0, $e); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,51 @@ | ||
<?php | ||
|
||
declare(strict_types=1); | ||
|
||
namespace Psl\Regex; | ||
|
||
use Psl\Type; | ||
|
||
use function preg_match; | ||
|
||
/** | ||
* Determine if $subject matches the given $pattern and return the first matches. | ||
* | ||
* @template T of array|null | ||
* | ||
* @param non-empty-string $pattern The pattern to match against. | ||
* @param ?Type\TypeInterface<T> $capture_groups What shape does the matching items have? | ||
* | ||
* @throws Exception\RuntimeException If an internal error accord. | ||
* @throws Exception\InvalidPatternException If $pattern is invalid. | ||
* | ||
* @return (T is null ? array<array-key, string> : T)|null | ||
*/ | ||
function first_match( | ||
string $subject, | ||
string $pattern, | ||
?Type\TypeInterface $capture_groups = null, | ||
int $offset = 0 | ||
): ?array { | ||
$matching = Internal\call_preg( | ||
'preg_match', | ||
static function () use ($subject, $pattern, $offset): ?array { | ||
$matching = []; | ||
$matches = preg_match($pattern, $subject, $matching, 0, $offset); | ||
|
||
return $matches === 0 ? null : $matching; | ||
} | ||
); | ||
|
||
if ($matching === null) { | ||
return null; | ||
} | ||
|
||
$capture_groups ??= Type\dict(Type\array_key(), Type\string()); | ||
|
||
try { | ||
return $capture_groups->coerce($matching); | ||
} catch (Type\Exception\CoercionException $e) { | ||
throw new Exception\RuntimeException('Invalid capture groups', 0, $e); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
<?php | ||
|
||
declare(strict_types=1); | ||
|
||
namespace Psl\Tests\Regex; | ||
|
||
use PHPUnit\Framework\TestCase; | ||
|
||
use function Psl\Regex\capture_groups; | ||
|
||
final class CaptureGroupsTest extends TestCase | ||
{ | ||
public function testItAlwaysAddsZeroCaptureResult(): void | ||
{ | ||
$data = [0 => 'Hello', 1 => 'World']; | ||
$shape = capture_groups([1]); | ||
$actual = $shape->coerce($data); | ||
|
||
static::assertSame($actual, $data); | ||
} | ||
} |
Oops, something went wrong.