Completed
Push — master ( 066343...e5de66 )
by Nico
01:23
created

Tokenizer::getPriority()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

Changes 0
Metric Value
dl 0
loc 4
ccs 0
cts 2
cp 0
rs 10
c 0
b 0
f 0
cc 1
eloc 2
nc 1
nop 1
crap 2
1
<?php
2
3
declare(strict_types=1);
4
5
/**
6
 * @license     http://opensource.org/licenses/mit-license.php MIT
7
 * @link        https://github.com/nicoSWD
8
 * @author      Nicolas Oelgart <[email protected]>
9
 */
10
namespace nicoSWD\Rules;
11
12
use nicoSWD\Rules\Tokens\TokenFactory;
13
use SplPriorityQueue;
14
use stdClass;
15
16
final class Tokenizer implements TokenizerInterface
17
{
18
    /** @var TokenFactory */
19
    private $tokenFactory;
20
21
    private $internalTokens = [];
22
23
    private $regex = '';
24
25 236
    public function __construct(Grammar $grammar, TokenFactory $tokenFactory)
26
    {
27 236
        $this->tokenFactory = $tokenFactory;
28
29 236
        foreach ($grammar->getDefinition() as list($class, $regex, $priority)) {
30 236
            $this->registerToken($class, $regex, $priority);
31
        }
32 236
    }
33
34 226
    public function tokenize(string $string): Stack
35
    {
36 226
        $stack = new Stack();
37 226
        $regex = $this->getRegex();
38 226
        $offset = 0;
39
40 226
        while (preg_match($regex, $string, $matches, 0, $offset)) {
41 224
            $token = $this->getMatchedToken($matches);
42 224
            $className = $this->tokenFactory->createFromTokenName($token);
43
44 224
            $stack->attach(new $className(
45 224
                $matches[$token],
46 224
                $offset,
47 224
                $stack
48
            ));
49
50 224
            $offset += strlen($matches[0]);
51
        }
52
53 226
        return $stack;
54
    }
55
56 236
    private function registerToken(string $class, string $regex, int $priority)
57
    {
58 236
        $token = new stdClass();
59 236
        $token->class = $class;
60 236
        $token->regex = $regex;
61 236
        $token->priority = $priority;
62
63 236
        $this->internalTokens[$class] = $token;
64 236
    }
65
66 226
    private function getMatchedToken(array $matches): string
67
    {
68 226
        foreach ($matches as $key => $value) {
69 224
            if ($value !== '' && !is_int($key)) {
70 224
                return $key;
71
            }
72
        }
73
74 2
        return 'Unknown';
75
    }
76
77 226
    private function getRegex(): string
78
    {
79 226
        if (!$this->regex) {
80 226
            $regex = [];
81
82 226
            foreach ($this->getQueue() as $token) {
83 226
                $regex[] = "(?<$token->class>$token->regex)";
84
            }
85
86 226
            $this->regex = '~(' . implode('|', $regex) . ')~As';
87
        }
88
89 226
        return $this->regex;
90
    }
91
92 226
    private function getQueue(): SplPriorityQueue
93
    {
94 226
        $queue = new SplPriorityQueue();
95
96 226
        foreach ($this->internalTokens as $class) {
97 226
            $queue->insert($class, $class->priority);
98
        }
99
100 226
        return $queue;
101
    }
102
}
103