mirror of https://github.com/ghostfolio/ghostfolio
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
100 lines
2.8 KiB
100 lines
2.8 KiB
<?php declare(strict_types=1);
|
|
|
|
/**
|
|
* @package s9e\RegexpBuilder
|
|
* @copyright Copyright (c) The s9e authors
|
|
* @license https://opensource.org/licenses/mit-license.php The MIT License
|
|
*/
|
|
namespace s9e\RegexpBuilder;
|
|
|
|
use function array_map;
|
|
use s9e\RegexpBuilder\Input\Bytes as BytesInput;
|
|
use s9e\RegexpBuilder\Input\InputInterface;
|
|
use s9e\RegexpBuilder\Output\Bytes as BytesOutput;
|
|
use s9e\RegexpBuilder\Output\OutputInterface;
|
|
use s9e\RegexpBuilder\Passes\CoalesceOptionalStrings;
|
|
use s9e\RegexpBuilder\Passes\CoalesceSingleCharacterPrefix;
|
|
use s9e\RegexpBuilder\Passes\GroupSingleCharacters;
|
|
use s9e\RegexpBuilder\Passes\MergePrefix;
|
|
use s9e\RegexpBuilder\Passes\MergeSuffix;
|
|
use s9e\RegexpBuilder\Passes\PromoteSingleStrings;
|
|
use s9e\RegexpBuilder\Passes\Recurse;
|
|
|
|
class Builder
|
|
{
|
|
public readonly Runner $runner;
|
|
public readonly Serializer $serializer;
|
|
|
|
/**
|
|
* @var bool Whether the expression generated is meant to be used whole. If not, alternations
|
|
* will be put into a non-capturing group
|
|
*/
|
|
public bool $standalone = true;
|
|
|
|
public function __construct(
|
|
public readonly InputInterface $input = new BytesInput,
|
|
public readonly Meta $meta = new Meta,
|
|
public readonly OutputInterface $output = new BytesOutput
|
|
)
|
|
{
|
|
$this->serializer = new Serializer($this->meta, $this->output);
|
|
$this->setRunner();
|
|
}
|
|
|
|
/**
|
|
* Build and return a regular expression that matches all of the given strings
|
|
*
|
|
* @param string[] $strings Literal strings to be matched
|
|
* @return string Regular expression (without delimiters)
|
|
*/
|
|
public function build(array $strings): string
|
|
{
|
|
$strings = $this->getInputSplitter()->splitStrings($strings);
|
|
$strings = $this->getStringSorter()->getUniqueSortedStrings($strings);
|
|
if ($this->isEmpty($strings))
|
|
{
|
|
return '';
|
|
}
|
|
$strings = $this->runner->run($strings);
|
|
|
|
return $this->serializer->serializeStrings($strings, !$this->standalone);
|
|
}
|
|
|
|
protected function getInputSplitter(): InputSplitter
|
|
{
|
|
return new InputSplitter($this->input, $this->meta);
|
|
}
|
|
|
|
public function getStringSorter(): StringSorter
|
|
{
|
|
return new StringSorter;
|
|
}
|
|
|
|
/**
|
|
* Test whether the list of strings is empty
|
|
*
|
|
* @param array<array> $strings
|
|
* @return bool
|
|
*/
|
|
protected function isEmpty(array $strings): bool
|
|
{
|
|
return (empty($strings) || $strings === [[]]);
|
|
}
|
|
|
|
/**
|
|
* Set the Runner instance $in this->runner
|
|
*
|
|
* @return void
|
|
*/
|
|
protected function setRunner(): void
|
|
{
|
|
$this->runner = new Runner;
|
|
$this->runner->addPass(new MergePrefix);
|
|
$this->runner->addPass(new GroupSingleCharacters);
|
|
$this->runner->addPass(new Recurse($this->runner));
|
|
$this->runner->addPass(new PromoteSingleStrings);
|
|
$this->runner->addPass(new CoalesceOptionalStrings);
|
|
$this->runner->addPass(new MergeSuffix);
|
|
$this->runner->addPass(new CoalesceSingleCharacterPrefix);
|
|
}
|
|
}
|